package org.sang.utils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class AESUtil {
    // 指定算法类型
    public static String AES = "AES";
    // 指定秘钥长度
    public static int KEY_LEN = 128;
    // 指定编码格式
    public static String UTF_8 = "UTF-8";

    /**
     * 生成 AES 秘钥
     * @return aesKey
     */
    public static String genAESKey() throws Exception{
        // 构造秘钥生成器，指定 AES 算法
        KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
        // 生成一个指定位数的随机源，KEY_LEN=128 就是 128位
        keyGenerator.init(KEY_LEN);
        // 生成对称秘钥
        SecretKey secretKey = keyGenerator.generateKey();
        return Base64.getEncoder().encodeToString(secretKey.getEncoded());
    }

    /**
     * AES 算法加密
     * @param key 秘钥
     * @param data 待加密字符串数据
     * @return encryptData
     */
    public static String encrypt(String key, String data) throws Exception{
        // 获取key
        SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(key.getBytes()), AES);
        // 根据指定算法生成密码器
        Cipher cipher = Cipher.getInstance(AES);
        // 初始化密码器
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        // 将加密内容转成字节数组
        byte[] byteData = data.getBytes(UTF_8);
        // 将字节数组加密
        byte[] aesData = cipher.doFinal(byteData);
        return new String(Base64.getEncoder().encode(aesData));
    }

    /**
     * AES 算法解密
     * @param key 秘钥
     * @param data 待解密字符串数据
     * @return decryptData
     */
    public static String decrypt(String key, String data) throws Exception{
        // 获取 key
        SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(key.getBytes()), AES);
        // 根据指定算法生成密码器
        Cipher cipher = Cipher.getInstance(AES);
        // 初始化密码器
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        // 将加密内容转换为字节数组，因数据是使用 Base64 转换过的，所以需要使用Base64解密
        byte[] dataByte = Base64.getDecoder().decode(data.getBytes(UTF_8));
        // 解密字节数组
        byte[] decryptData = cipher.doFinal(dataByte);
        return new String(decryptData);
    }

}
